#pragma once

//#include <windows.h>

#define WINVER 0x0500		// Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#define _WIN32_WINNT 0x0500		// Change this to the appropriate value to target Windows 98 and Windows 2000 or later.


#define UD_WEAVE_REQUEST 128
#define UD_UNWEAVE_REQUEST 129


#include <afxwin.h>
#include <stdio.h>
#include <tchar.h>
#include <afxdb.h>
#include "myaspects_dac.h"
#include "Winsvc.h"

void  __stdcall  Service_Main(DWORD dwArgc, LPTSTR *lpszArgv);
void  __stdcall  Service_Ctrl(DWORD dwCtrlCode);


#import "msado15.dll" rename_namespace("ADODB") rename("EOF", "ADOEOF")

ADODB::_ConnectionPtr cn;
char* CONNECTION_URL = NULL;

const char* CONNECTSTRING_FUNC()
{
  DWORD dwSize = 256;
  char szServer[256], szDatabase[256], szUser[256], szPassword[256];

  if (NULL == CONNECTION_URL) {
    ::GetPrivateProfileString("Repository", "Server", "localhost",szServer,dwSize, "InfobusPrototype.ini");
    ::WritePrivateProfileString("Repository", "Server", szServer, "InfobusPrototype.ini");

    ::GetPrivateProfileString("Repository", "Database", "demo",szDatabase,dwSize, "InfobusPrototype.ini");
    ::WritePrivateProfileString("Repository", "Database", szDatabase, "InfobusPrototype.ini");

    ::GetPrivateProfileString("Repository", "User", "demo",szUser,dwSize, "InfobusPrototype.ini");
    ::WritePrivateProfileString("Repository", "User", szUser, "InfobusPrototype.ini");

    ::GetPrivateProfileString("Repository", "Password", "demo",szPassword,dwSize, "InfobusPrototype.ini");
    ::WritePrivateProfileString("Repository", "Password", szPassword, "InfobusPrototype.ini");

    _bstr_t connstr = _bstr_t("Driver={SQL Native Client};Server="+_bstr_t(szServer)+";Database="+_bstr_t(szDatabase)+"; Uid="+_bstr_t(szUser)+";Pwd="+_bstr_t(szPassword)+";");

    CONNECTION_URL = new char[connstr.length()+1];
    memset(CONNECTION_URL, 0, connstr.length()+1);
    strncpy(CONNECTION_URL, connstr, connstr.length());
  }

  return CONNECTION_URL;
}

#define CONNECTSTRING CONNECTSTRING_FUNC()


HANDLE  hStopEvent,hWeaveEvent,hUnweaveEvent;


void  SetTheServiceStatus(DWORD dwCurrentState,DWORD dwWin32ExitCode,DWORD dwCheckPoint,  DWORD dwWaitHint);

   LPTSTR  lpszServiceName;
   SERVICE_STATUS_HANDLE   ssh;


void ErrorStopService(LPTSTR lpszAPI)
{
   INT t;
   TCHAR   buffer[256]  = TEXT("");
   TCHAR   error[1024]  = TEXT("");
   LPVOID lpvMessageBuffer;
   DWORD  dwWaitRes;

   wsprintf(buffer,TEXT("API = %s, "), lpszAPI);
   lstrcat(error, buffer);

   ZeroMemory(buffer, sizeof(buffer));
   wsprintf(buffer,TEXT("error code = %d, "), GetLastError());
   lstrcat(error, buffer);

   // Obtain the error string.
   FormatMessage(
      FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
      NULL, GetLastError(),
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      (LPTSTR)&lpvMessageBuffer, 0, NULL);

   ZeroMemory((LPVOID)buffer, (DWORD)sizeof(buffer));
   wsprintf(buffer,TEXT("message = %s"), (TCHAR *)lpvMessageBuffer);
   lstrcat(error, buffer);

   // Free the buffer allocated by the system.
   LocalFree(lpvMessageBuffer);

   // Write the error string to the debugger.
   OutputDebugString(error);

   // If you have threads running, tell them to stop. Something went
   // wrong, and you need to stop them so you can inform the SCM.
   SetEvent(hStopEvent);


   // Stop the service.
   SetTheServiceStatus(SERVICE_STOPPED, GetLastError(), 0, 0);
}

class Thread
{
	static DWORD __stdcall ThreadFunc(LPVOID pv)
	{
		try
		{
			(reinterpret_cast<Thread *>(pv))->run();
		}
		catch(...)
		{
			OutputDebugString("* Err: ThreadFunc\n");
		}
		return 0;
	}

public:
	typedef DWORD ThreadId;

	Thread()
  	: bTerminated(false)
	{
    LockMutex = ::CreateMutex(NULL, FALSE, "MutexToPreventMultipleExecution");
	}
	virtual ~Thread()
	{
	}
	static ThreadId 
_org_getThreadId
()
	{
		return ::GetCurrentThreadId();
	}
	static void 
_org_sleep
(long milliseconds=1000)
	{
		::Sleep(milliseconds);
	}
	ThreadId 
_org_start
()
	{
		ThreadId id;
		::CreateThread(NULL, 0, ThreadFunc, this, 0, &id);
		return id;
	}
  bool 
_org_waitForLock
()
  {
    DWORD dwWaitResult = ::WaitForSingleObject(LockMutex, INFINITE);
    return true;
  }
  void 
_org_releaseLock
()
  {
    ::ReleaseMutex(LockMutex);
  }
  void 
_org_terminate
()
  {
	  bTerminated = true;
  }
  bool 
_org_isTerminated
()
  {
	  return bTerminated;
  }
  virtual void 
_org_run
() = 0;

protected:
  bool bTerminated;
  HANDLE LockMutex;
public : static ThreadId getThreadId (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[3].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[3].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(3,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   DWORD _rvalue  = _org_getThreadId ();
   if  (MethodMOP[3].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[3].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(3,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public : static void sleep ( long milliseconds = 1000 ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[4].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[4].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(4,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   _org_sleep ( milliseconds ) ;
   if  (MethodMOP[4].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[4].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(4,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  ThreadId start (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[5].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[5].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(5,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   DWORD _rvalue  = _org_start ();
   if  (MethodMOP[5].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[5].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(5,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  bool waitForLock (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[6].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[6].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(6,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   bool _rvalue  = _org_waitForLock ();
   if  (MethodMOP[6].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[6].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(6,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  void releaseLock (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[7].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[7].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(7,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_releaseLock ();
  if  (MethodMOP[7].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[7].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(7,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void terminate (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[8].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[8].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(8,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_terminate ();
  if  (MethodMOP[8].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[8].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(8,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  bool isTerminated (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[9].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[9].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(9,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   bool _rvalue  = _org_isTerminated ();
   if  (MethodMOP[9].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[9].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(9,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public : virtual void run (  ) = 0 {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[10].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[10].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(10,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_run ();
  if  (MethodMOP[10].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[10].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(10,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
 

};


class FileThread : public Thread
{
public:
  FileThread();
  ~FileThread();
  void 
_org_open
();
  void 
_org_reopen
();
  virtual void 
_org_run
();
  void 
_org_writeToFile
(const char* pszdata);
private:
	FILE * fp;
public :  void open (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[13].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[13].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(13,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_open ();
  if  (MethodMOP[13].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[13].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(13,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void reopen (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[14].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[14].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(14,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_reopen ();
  if  (MethodMOP[14].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[14].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(14,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public : virtual void run (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[15].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[15].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(15,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_run ();
  if  (MethodMOP[15].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[15].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(15,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void writeToFile ( const char * pszdata ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[16].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[16].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(16,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   _org_writeToFile ( pszdata ) ;
   if  (MethodMOP[16].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[16].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(16,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public : static ThreadId getThreadId (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[19].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[19].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(19,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   DWORD _rvalue  = _org_getThreadId ();
   if  (MethodMOP[19].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[19].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(19,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public : static void sleep ( long milliseconds = 1000 ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[20].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[20].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(20,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   _org_sleep ( milliseconds ) ;
   if  (MethodMOP[20].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[20].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(20,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  ThreadId start (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[21].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[21].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(21,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   DWORD _rvalue  = _org_start ();
   if  (MethodMOP[21].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[21].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(21,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  bool waitForLock (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[22].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[22].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(22,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   bool _rvalue  = _org_waitForLock ();
   if  (MethodMOP[22].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[22].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(22,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  void releaseLock (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[23].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[23].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(23,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_releaseLock ();
  if  (MethodMOP[23].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[23].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(23,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void terminate (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[24].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[24].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(24,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_terminate ();
  if  (MethodMOP[24].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[24].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(24,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  bool isTerminated (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[25].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[25].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(25,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   bool _rvalue  = _org_isTerminated ();
   if  (MethodMOP[25].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[25].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(25,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
 

};

const char* FILENAME = "c:\\filewriting.txt";
const char* FILENAME2 = "c:\\filewriting2.txt";

FileThread::FileThread()
: fp(NULL)
{
	OutputDebugString("FileThread::FileThread()\n");
}

FileThread::~FileThread()
{
  OutputDebugString("FileThread::~FileThread()\n");

  fclose(fp);
  fp = NULL;
}

void FileThread::
_org_run
()
{
  OutputDebugString("FileThread::run()\n");

  const char* szData = "Data is being written\r\n";

  open();
  while (!isTerminated()) {
    try {
      if (waitForLock()) {
        OutputDebugString("Writes to file...\n");
		writeToFile(szData);
        releaseLock();
      }
      sleep(1000);
    } catch (...) {
      reopen();
    }
  }
}

void FileThread::
_org_writeToFile
(const char* pszdata)
{
	int written = 0;
	if (fp) written = fwrite(pszdata, 1, strlen(pszdata), fp);
	if (written != strlen(pszdata)) throw("Data not written properly");
}

void FileThread::
_org_open
()
{
  OutputDebugString("FileThread::open()\n");
  try {
	  while (!fp) {
		fp = fopen(FILENAME, "a+b");
		if (!fp) sleep(1000); // To avoid starvation
	  }
  } catch (...) {
  }
}

void FileThread::
_org_reopen
()
{
  if (fp) {
    fclose(fp);
    fp = NULL;
  }
  open();
}





class DatabaseThread : public Thread
{
public:
  DatabaseThread();
  ~DatabaseThread();
	void 
_org_open
();
  void 
_org_reopen
();
  virtual void 
_org_run
();
  void 
_org_writeToDatabase
();
private:
  bool cnOpen;
  CDatabase theDatabase;
public :  void open (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[28].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[28].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(28,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_open ();
  if  (MethodMOP[28].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[28].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(28,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void reopen (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[29].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[29].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(29,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_reopen ();
  if  (MethodMOP[29].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[29].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(29,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public : virtual void run (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[30].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[30].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(30,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_run ();
  if  (MethodMOP[30].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[30].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(30,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void writeToDatabase (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[31].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[31].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(31,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_writeToDatabase ();
  if  (MethodMOP[31].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[31].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(31,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public : static ThreadId getThreadId (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[34].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[34].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(34,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   DWORD _rvalue  = _org_getThreadId ();
   if  (MethodMOP[34].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[34].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(34,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public : static void sleep ( long milliseconds = 1000 ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[35].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[35].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(35,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   _org_sleep ( milliseconds ) ;
   if  (MethodMOP[35].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[35].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(35,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  ThreadId start (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[36].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[36].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(36,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   DWORD _rvalue  = _org_start ();
   if  (MethodMOP[36].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[36].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(36,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  bool waitForLock (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[37].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[37].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(37,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   bool _rvalue  = _org_waitForLock ();
   if  (MethodMOP[37].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[37].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(37,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  void releaseLock (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[38].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[38].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(38,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_releaseLock ();
  if  (MethodMOP[38].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[38].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(38,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void terminate (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[39].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[39].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(39,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_terminate ();
  if  (MethodMOP[39].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[39].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(39,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  bool isTerminated (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[40].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[40].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(40,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   bool _rvalue  = _org_isTerminated ();
   if  (MethodMOP[40].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[40].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(40,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
 



};



DatabaseThread::DatabaseThread()
: cnOpen(false)
{
  OutputDebugString("DatabaseThread::DatabaseThread()\n");
}

DatabaseThread::~DatabaseThread()
{
  OutputDebugString("DatabaseThread::~DatabaseThread()\n");
  if (theDatabase.IsOpen())
	   theDatabase.Close();

}

void DatabaseThread::
_org_run
()
{
  OutputDebugString("DatabaseThread::run()\n");

  try {
    open();
  } catch (_com_error& e) {
    TCHAR buffer[0x1000] = { 0 };
    sprintf(buffer, "%s [%ld]\n", e.ErrorMessage(), e.Error());
    OutputDebugString(buffer);
    try { cn->Close(); } catch (...) { }
    cnOpen = false;
  } catch (...) {
  }

  while (!isTerminated()) {
    try {
      if (waitForLock()) {
        OutputDebugString("Writes to database...\n");
		writeToDatabase();
        releaseLock();
      }
      sleep(1000);
    } catch (...) {
      reopen();
    }
  }
}

void DatabaseThread::
_org_writeToDatabase
()
{
  	HRESULT hr;
	bstr_t sql = "INSERT INTO SAMPLE_DATA (DATA) VALUES ('Data is being written')";
	hr = cn->Execute(sql, NULL, ADODB::adExecuteNoRecords);
	if (S_OK != hr) throw("Data not written properly");
	try { hr = cn->CommitTrans(); } catch (...) { }
}

void DatabaseThread::
_org_open
()
{
  OutputDebugString("DatabaseThread::open()\n");

  HRESULT hr;
  bstr_t cns;

  ::CoInitialize(NULL);

  hr = cn.CreateInstance(__uuidof(ADODB::Connection), NULL, CLSCTX_INPROC_SERVER);
  if (S_OK != hr) throw("CreateInstance failed");
  cns = bstr_t(CONNECTSTRING);

  while (!cnOpen) {
    try {
      hr = cn->Open(cns, "", "", -1);
      if (S_OK != hr) throw("Database not opened properly");
      cnOpen = true;
    } catch (_com_error& e) {
      TCHAR buffer[0x1000] = { 0 };
      sprintf(buffer, "%s [%ld]\n", e.ErrorMessage(), e.Error());
      OutputDebugString(buffer);
      try { cn->Close(); } catch (...) { }
      cnOpen = false;
    }
    if (!cnOpen) sleep(1000);
  }
}

void DatabaseThread::
_org_reopen
()
{
  OutputDebugString("DatabaseThread::reopen()\n");

  try { cn->Close(); } catch (...) { }
  cnOpen = false;

  open();
}





int display_menu()

{
int option;
		 do {

		 std::cout<<endl<<endl;

		std::cout<<"		  1.  Weave AspectA"					<<endl;
		std::cout<<"		  2.  Weave AspectB"					<<endl;

		std::cout<<"		  3.  Unweave AspectA"					<<endl;
		std::cout<<"		  4.  Unweave Aspect B "				<<endl;


		std::cout<<"		  5.  Exit      "       				<<endl;

		std::cin>> option;

		if((option >=1)&&(option<=5))
			break;

		system("cls");
		std::cout<<endl<<"        !!!! You have selected wrong option!"<<endl<<endl;

		 } while(true); // end of do




		 return option;

}; // end of Display Menu






AspectA a1;
AspectB b1;
NetworkPC  net1;
ApplicationPC app1;
MethodPC   meth1,meth2;
ClassPC   classpc1,classpc2;

PCD  pc1,pc2;
WeaveSpecs ws1,ws2;

void _tmain(int argc, TCHAR *argv[])
{
   SERVICE_TABLE_ENTRY ste[] =
      {{TEXT(""),(LPSERVICE_MAIN_FUNCTION)Service_Main}, {NULL, NULL}};

   OutputDebugString(TEXT("Entered service code\n"));
   if (!StartServiceCtrlDispatcher(ste))
   {
      TCHAR error[256];


      wsprintf(error,
         TEXT("Error code for StartServiceCtrlDispatcher: %u.\n"),
         GetLastError());
      OutputDebugString(error);
   }
   else
      OutputDebugString(TEXT("StartServiceCtrlDispatcher returned!\n"));
}

// Called by the service control manager after the call to
// StartServiceCtrlDispatcher.

void __stdcall Service_Main(DWORD dwArgc, LPTSTR *lpszArgv)
{
   DWORD ThreadId;
   DWORD t;
   DWORD dwWaitRes;

   // Obtain the name of the service.
   lpszServiceName = lpszArgv[0];

   // Register the service ctrl handler.
   ssh = RegisterServiceCtrlHandler(lpszServiceName,
           (LPHANDLER_FUNCTION)Service_Ctrl);

   // Create the event to signal the service to stop.
   hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
   if (hStopEvent == NULL)
      ErrorStopService(TEXT("CreateEvent"));


   hWeaveEvent= CreateEvent(NULL, TRUE, FALSE, NULL);
   if (hWeaveEvent == NULL)
      ErrorStopService(TEXT("CreateEvent"));

   hUnweaveEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
   if (hUnweaveEvent== NULL)
      ErrorStopService(TEXT("CreateEvent"));


   // The service has started.
   SetTheServiceStatus(SERVICE_RUNNING, 0, 0, 0);
   OutputDebugString(TEXT("SetTheServiceStatus, SERVICE_RUNNING\n"));



   //Sleep(20000);


   	 int option;
	 bool done;

	 FileThread *fileWriting;
	 Thread *databaseWriting;

	 DAC_INIT();

     meth2.setvalue("*");
	 classpc2.setvalue("*");


   pc2.setmethodPC(meth2);
   pc2.setclassPC(classpc2);

   ws2.setweavetype(Before_T);



   b1.setweavespecs(ws2);
   b1.setpcd(pc2);

	 fileWriting = new FileThread();
	 fileWriting->start();


	databaseWriting = new DatabaseThread();
	databaseWriting->start();




   while(WaitForSingleObject(hStopEvent, 10) != WAIT_OBJECT_0)
   {
	   try
	   {
			if (WaitForSingleObject(hWeaveEvent, 1) == WAIT_OBJECT_0)
			{


			   weave(&b1);

				if (!ResetEvent(hWeaveEvent))
						ErrorStopService(TEXT("ResetEvent hWeaveEvent"));

			}

			if (WaitForSingleObject(hUnweaveEvent, 1) == WAIT_OBJECT_0)
			{



				unweave(&b1);

				if (!ResetEvent(hUnweaveEvent))
						ErrorStopService(TEXT("ResetEvent hUnweaveEvent"));


			}





	   }
	   catch(...) // to make sure this loop always continue regardless
	   {

	   }



   } // end of while for service main loop




   //fileWriting->terminate();

 delete fileWriting;
 delete databaseWriting;


   OutputDebugString(TEXT("SetTheServiceStatus, SERVICE_STOPPED\n"));
   SetTheServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0);
}

// Handles control signals from the service control manager.

void __stdcall Service_Ctrl(DWORD dwCtrlCode)
{
   DWORD dwState = SERVICE_RUNNING;

   switch(dwCtrlCode)
   {
      case SERVICE_CONTROL_STOP:
         dwState = SERVICE_STOP_PENDING;
         break;

      case SERVICE_CONTROL_SHUTDOWN:
         dwState = SERVICE_STOP_PENDING;
         break;

      case SERVICE_CONTROL_INTERROGATE:
         break;

	  case UD_WEAVE_REQUEST:
		   if (!SetEvent(hWeaveEvent))
			   ErrorStopService(TEXT("SetEvent for hWeaveEvent"));

		  break;

	  case UD_UNWEAVE_REQUEST:

		  if (!SetEvent(hUnweaveEvent))
			  ErrorStopService(TEXT("SetEvent for hUnweaveEvent"));
			 break;

      default:
         break;
   }

   // Set the status of the service.
   SetTheServiceStatus(dwState, NO_ERROR, 0, 0);
   OutputDebugString(
       TEXT("SetTheServiceStatus, Service_Ctrl function\n"));

   // Tell service_main thread to stop.
   if ((dwCtrlCode == SERVICE_CONTROL_STOP) ||
       (dwCtrlCode == SERVICE_CONTROL_SHUTDOWN))
   {
      if (!SetEvent(hStopEvent))
         ErrorStopService(TEXT("SetEvent"));
      else
         OutputDebugString(TEXT("Signal service_main thread\n"));


/*
       if (!SetEvent(hStopRepEvent))
           ErrorStopService(TEXT("SetEvent for Stop Replication"));
       else
           OutputDebugString(TEXT("Signal Service Main thread to Stop replication\n"));

*/

   }

   OutputDebugString(TEXT("inside Service_Ctrl\n"));




}


void SetTheServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
                         DWORD dwCheckPoint,   DWORD dwWaitHint)
{
   SERVICE_STATUS ss;  // Current status of the service.

   // Disable control requests until the service is started.
   if (dwCurrentState == SERVICE_START_PENDING)
      ss.dwControlsAccepted = 0;
   else
      ss.dwControlsAccepted =
         SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
         // Other flags include SERVICE_ACCEPT_PAUSE_CONTINUE
         // and SERVICE_ACCEPT_SHUTDOWN.

   // Initialize ss structure.
   ss.dwServiceType             = SERVICE_WIN32_OWN_PROCESS;
   ss.dwServiceSpecificExitCode = 0;
   ss.dwCurrentState            = dwCurrentState;
   ss.dwWin32ExitCode           = dwWin32ExitCode;
   ss.dwCheckPoint              = dwCheckPoint;
   ss.dwWaitHint                = dwWaitHint;

   // Send status of the service to the Service Controller.
   if (!SetServiceStatus(ssh, &ss))
      ErrorStopService(TEXT("SetServiceStatus"));
}
